package com.code2roc.miniflow.base.util;

import com.code2roc.miniflow.base.annotation.MiniFlowAutowired;
import com.code2roc.miniflow.base.annotation.MiniFlowComponent;
import com.code2roc.miniflow.base.annotation.MiniFlowService;

import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class MiniFlowResourceUtil {
    private static final ConcurrentHashMap<Class<?>, Object> beanContainter = new ConcurrentHashMap<>();

    public static void init(String ...scanPackage){
        try{
            List<Class<?>> waitRegistClassList =  MiniFlowScanUtil.getAllClassByPackageName_Annotation("com.code2roc.miniflow", MiniFlowService.class);
            for(Class clazz:waitRegistClassList){
                register(clazz,clazz.newInstance());
            }
            List<Class<?>> waitInjectClassList =  MiniFlowScanUtil.getAllClassByPackageName_Annotation("com.code2roc.miniflow", MiniFlowComponent.class);
            for(String packageName:scanPackage){
                List<Class<?>> extraList =  MiniFlowScanUtil.getAllClassByPackageName_Annotation(packageName, MiniFlowComponent.class);
                waitInjectClassList.addAll(extraList);
            }
            for(Class clazz:waitInjectClassList){
                inject(clazz);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void register(Class<?> registClass, Object instance) {
        if(!beanContainter.contains(registClass)){
            beanContainter.put(registClass, instance);
        }
    }

    private static void inject(Class<?> injectClass) {
        for (Field field : injectClass.getDeclaredFields()) {
            if (java.lang.reflect.Modifier.isStatic(field.getModifiers())
                    && field.isAnnotationPresent(MiniFlowAutowired.class)) {
                Object dependency = beanContainter.get(field.getType());
                if (dependency != null) {
                    field.setAccessible(true);
                    try {
                        field.set(null, dependency);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("static field inject fail: " + field.getName(), e);
                    }
                }
            }
        }
    }
}
